package com.zshan.clinic.admin.service.medical;


import com.fasterxml.jackson.core.type.TypeReference;
import com.zshan.clinic.admin.entity.dto.AddInfusionFeeDTO;
import com.zshan.clinic.admin.entity.dto.MemberConsumeDTO;
import com.zshan.clinic.admin.entity.dto.OrderPayDTO;
import com.zshan.clinic.admin.entity.medical.emp.ClinicEmpSimple;
import com.zshan.clinic.admin.entity.medical.exam.ExamDetail;
import com.zshan.clinic.admin.entity.medical.order.charge.ChargeOrderBO;
import com.zshan.clinic.admin.entity.medical.order.charge.ChargeOrderRecordDetail;
import com.zshan.clinic.admin.entity.medical.order.charge.OrderItemDetail;
import com.zshan.clinic.admin.entity.medical.rx.RxDrug;
import com.zshan.clinic.admin.entity.medical.rx.RxExt;
import com.zshan.clinic.admin.entity.medical.rx.RxInfusion;
import com.zshan.clinic.admin.entity.medical.rx.RxTcm;
import com.zshan.clinic.admin.entity.medical.rx.base.*;
import com.zshan.clinic.admin.entity.vo.*;
import com.zshan.clinic.admin.entity.vo.print.ChargeOrderPrintVo;
import com.zshan.clinic.admin.mapper.medical.SpecChargeOrderMapper;
import com.zshan.clinic.admin.service.clinic.ClinicEmpService;
import com.zshan.clinic.admin.service.config.PrintConfigService;
import com.zshan.clinic.admin.service.patient.ClinicMemberService;
import com.zshan.clinic.admin.task.AsyncTaskService;
import com.zshan.clinic.common.constant.CommonConstant;
import com.zshan.clinic.common.constant.UnitConstant;
import com.zshan.clinic.common.enums.*;
import com.zshan.clinic.common.exception.BusinessFailException;
import com.zshan.clinic.common.util.json.JsonUtil;
import com.zshan.clinic.common.util.page.PageUtils;
import com.zshan.clinic.common.util.string.StringUtil;
import com.zshan.clinic.common.util.uuid.IdBuilder;
import com.zshan.clinic.database.dao.ChargeOrderItemMapper;
import com.zshan.clinic.database.dao.ChargeOrderMapper;
import com.zshan.clinic.database.dao.ChargeOrderRecordMapper;
import com.zshan.clinic.database.model.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 收费单
 * @author lichen
 */
@Service
public class ChargeOrderService {

    @Autowired
    private ChargeOrderMapper chargeOrderMapper;

    @Autowired
    private ChargeOrderItemMapper chargeOrderItemMapper;

    @Autowired
    private ChargeOrderRecordMapper chargeOrderRecordMapper;

    @Autowired
    private ClinicEmpService clinicEmpService;

    @Autowired
    private SpecChargeOrderMapper specChargeOrderMapper;

    @Autowired
    @Lazy
    private ClinicRegisterService registerService;

    @Autowired
    @Lazy
    private ClinicMedicalService clinicMedicalService;

    @Autowired
    private OrderExamService orderExamService;

    @Autowired
    private OrderDispenseService orderDispenseService;

    @Autowired
    private OrderExecService orderExecService;

    @Autowired
    private ClinicMemberService memberService;

    @Autowired
    private AsyncTaskService asyncTaskService;


    @Autowired
    private PrintConfigService printConfigService;

    /**
     * 打印收费单
     * @param clinicId
     * @param orderId
     * @param recordId
     * @return
     */
    public ChargeOrderPrintVo getChargeOrderPrint(Long clinicId, Long orderId, Long recordId,String printBy){
        if(StringUtil.isBlank(orderId) && StringUtil.isBlank(recordId)){
            throw new BusinessFailException("必须参数不能为空");
        }
        ClinicPrintConfigVo clinicPrintConfig = printConfigService.getConfigByCategoryAndType(clinicId,PrintCategoryEnum.RECEIPT.getValue(),Collections.singletonList(PrintTypeEnum.PAYMENT_RECEIPT.getValue()));
        if(clinicPrintConfig == null){
            throw new BusinessFailException("打印抬头未设置，请联系管理员处理！");
        }
        List<ChargeOrderRecord> chargeOrderRecordList = getChargeRecordList(orderId,recordId);
        if(CollectionUtils.isEmpty(chargeOrderRecordList)){
            throw new BusinessFailException("收费记录不存在");
        }
        //最后一次收费
        ChargeOrderRecord lastChargeOrderRecord = chargeOrderRecordList.get(chargeOrderRecordList.size() - 1);
        //合计
        int totalAmount = chargeOrderRecordList.stream()
                .map(ChargeOrderRecord::getTotalAmount) // 拿到 Integer
                .filter(Objects::nonNull)               // 过滤掉 null
                .mapToInt(Integer::intValue)            // 转成 int
                .sum();
        //实付
        int paidAmount = chargeOrderRecordList.stream()
                .map(ChargeOrderRecord::getPaidAmount) // 拿到 Integer
                .filter(Objects::nonNull)               // 过滤掉 null
                .mapToInt(Integer::intValue)            // 转成 int
                .sum();
        //查询订单详情
        ChargeOrder chargeOrder = getOrderById(lastChargeOrderRecord.getOrderId());
        if(chargeOrder == null){
            throw new BusinessFailException("订单不存在");
        }
        //头部信息
        ChargeOrderPrintVo chargeOrderPrintVo = new ChargeOrderPrintVo();
        chargeOrderPrintVo.setPatientName(chargeOrder.getPatientName());
        chargeOrderPrintVo.setPatientGender(chargeOrder.getPatientGender());
        chargeOrderPrintVo.setAgeYear(chargeOrder.getAgeYear());
        chargeOrderPrintVo.setAgeMonth(chargeOrder.getAgeMonth());
        chargeOrderPrintVo.setPatientPhone(chargeOrder.getPatientPhone());
        chargeOrderPrintVo.setVisitNo(chargeOrder.getVisitNo());
        chargeOrderPrintVo.setDoctorName(chargeOrder.getDoctorName());
        //收费信息
        chargeOrderPrintVo.setItemList(chargeOrderRecordList.stream()
                .map(ChargeOrderRecord::getDetailListJson)
                .filter(Objects::nonNull)
                .flatMap(json -> JsonUtil.json2Obj(json, new TypeReference<List<ChargeOrderRecordDetail>>() {}).stream())
                .collect(Collectors.toList()));
        chargeOrderPrintVo.setTotalAmount(totalAmount);
        chargeOrderPrintVo.setPaidAmount(paidAmount);
        chargeOrderPrintVo.setPayChannel(lastChargeOrderRecord.getPayChannel());
        chargeOrderPrintVo.setChargeBy(lastChargeOrderRecord.getChargeBy());
        chargeOrderPrintVo.setChargeTime(lastChargeOrderRecord.getChargeTime());

        //---------------补充底部信息------------------
        chargeOrderPrintVo.setPrintBy(printBy);
        chargeOrderPrintVo.setPrintTime(new Date());
        chargeOrderPrintVo.setTitle(clinicPrintConfig.getTitle());
        chargeOrderPrintVo.setAddress(clinicPrintConfig.getAddress());
        chargeOrderPrintVo.setPhone(clinicPrintConfig.getPhone());
        return chargeOrderPrintVo;
    }


    public List<ChargeOrderRecord> getChargeRecordList(Long orderId,Long recordId){
        ChargeOrderRecordExample example = new ChargeOrderRecordExample();
        ChargeOrderRecordExample.Criteria criteria = example.createCriteria();
        if(!StringUtil.isBlank(orderId)){
            criteria.andOrderIdEqualTo(orderId);
        }
        if(!StringUtil.isBlank(recordId)){
            criteria.andRecordIdEqualTo(recordId);
        }
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        return chargeOrderRecordMapper.selectByExample(example);
    }

    /**
     * 查询订单收费记录
     * @param clinicId
     * @param orderId
     * @return
     */
    public List<ChargeOrderRecordVo> getChargeOrderRecordList(Long clinicId,Long orderId){
        List<ChargeOrderRecord> dbChargeOrderRecordList = getChargeOrderRecordListByExample(clinicId,orderId);
        if(CollectionUtils.isEmpty(dbChargeOrderRecordList)){
            return Collections.emptyList();
        }
        List<ChargeOrderRecordVo> chargeOrderRecordVoList = new ArrayList<>();
        for(ChargeOrderRecord chargeOrderRecord : dbChargeOrderRecordList){
            ChargeOrderRecordVo chargeOrderRecordVo = new ChargeOrderRecordVo();
            BeanUtils.copyProperties(chargeOrderRecord,chargeOrderRecordVo);
            chargeOrderRecordVo.setDetailList(JsonUtil.json2Obj(chargeOrderRecord.getDetailListJson(),
                    new TypeReference<List<ChargeOrderRecordDetail>>() {}));
            chargeOrderRecordVoList.add(chargeOrderRecordVo);
        }
        return chargeOrderRecordVoList;
    }

    /**
     * 查询收费记录
     * @param clinicId
     * @param orderId
     * @return
     */
    public List<ChargeOrderRecord> getChargeOrderRecordListByExample(Long clinicId,Long orderId){
        ChargeOrderRecordExample example = new ChargeOrderRecordExample();
        ChargeOrderRecordExample.Criteria criteria = example.createCriteria();
        criteria.andClinicIdEqualTo(clinicId);
        criteria.andOrderIdEqualTo(orderId);
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        example.setOrderByClause("record_id desc");
        return chargeOrderRecordMapper.selectByExample(example);
    }

    /**
     * 根据业务ID查询收费状态
     * @param itemType
     * @param refId
     * @return
     */
    public List<ChargeOrderItem> getOrderItemByRefId(Long clinicId,String itemType,Long refId){
        ChargeOrderItemExample example = new ChargeOrderItemExample();
        ChargeOrderItemExample.Criteria criteria = example.createCriteria();
        criteria.andClinicIdEqualTo(clinicId);
        criteria.andItemTypeEqualTo(itemType);
        criteria.andItemRefIdEqualTo(refId);
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        example.setOrderByClause("create_time desc");
        return chargeOrderItemMapper.selectByExample(example);
    }

    /**
     * 查询诊所今日待收费数
     * @param clinicId
     * @return
     */
    public Long getWaitingCount(Long clinicId) {
        ChargeOrderExample example = new ChargeOrderExample();
        ChargeOrderExample.Criteria criteria = example.createCriteria();
        criteria.andPayStatusEqualTo(PayStatusEnum.ORDERED.getValue());
        criteria.andVisitDateEqualTo(LocalDate.now());
        criteria.andClinicIdEqualTo(clinicId);
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        return chargeOrderMapper.countByExample(example);
    }
    /**
     * 查询订单列表
     * @param clinicId
     * @param patientName
     * @return
     */
    public List<ChargeOrderPageVo> getOrderList(Long clinicId, LocalDate visitDate, String patientName, Integer pageNo, Integer pageSize){
        //方便调试
//        if(visitDate == null){
//            visitDate = LocalDate.now();
//        }
        if(StringUtil.isNotBlank(patientName)){
            visitDate = null;
        }
        return specChargeOrderMapper.getOrderList(clinicId,visitDate,patientName, PageUtils.getOffset(pageNo,pageSize),pageSize);
    }

    /**
     * 获取订单详情
     * @param clinicId
     * @param orderId
     * @return
     */
    public ChargeOrderDetailVo getOrderDetail(Long clinicId,Long orderId){
        ChargeOrderDetailVo chargeOrderDetailVo = specChargeOrderMapper.getOrderDetail(clinicId,orderId);
        if(chargeOrderDetailVo == null){
            throw new BusinessFailException("订单不存在");
        }
        List<ChargeOrderItemVo> itemList = chargeOrderDetailVo.getItemList();
        for(ChargeOrderItemVo itemVo : itemList){
            itemVo.setDetailList(JsonUtil.json2Obj(itemVo.getDetailListJson(),
                    new TypeReference<List<OrderItemDetail>>() {}));
        }
        return chargeOrderDetailVo;
    }

    public ClinicEmpSimple handleClinicEmpSimple(ClinicMedicalDetailVo medicalDetail, Long createUserId, String createBy) {
        ClinicEmpSimple clinicEmpSimple = new ClinicEmpSimple();
        if(createUserId.equals(medicalDetail.getDoctorId())){
            clinicEmpSimple.setEmpId(createUserId);
            clinicEmpSimple.setEmpName(createBy);
            clinicEmpSimple.setDeptId(medicalDetail.getDeptId());
            clinicEmpSimple.setDeptName(medicalDetail.getDeptName());
        }else {
            clinicEmpSimple = clinicEmpService.getEmpSimple(medicalDetail.getClinicId(),createUserId);
        }
        return clinicEmpSimple;
    }

    /**
     * 病历收费单
     * @param medicalDetail
     */
    @Transactional(rollbackFor = Exception.class)
    public void createRxOrder(ClinicMedicalDetailVo medicalDetail,Long createUserId,String createBy) {
        // 创建收费单
        ClinicEmpSimple orderEmp = handleClinicEmpSimple(medicalDetail,createUserId,createBy);
        ChargeOrderBO chargeOrderBO = new ChargeOrderBO();
        chargeOrderBO.setVisitNo(medicalDetail.getVisitNo());
        chargeOrderBO.setVisitDate(medicalDetail.getVisitDate());
        chargeOrderBO.setPatientId(medicalDetail.getPatientId());
        chargeOrderBO.setPatientName(medicalDetail.getPatientName());
        chargeOrderBO.setPatientGender(medicalDetail.getPatientGender());
        chargeOrderBO.setPatientPhone(medicalDetail.getPatientPhone());
        chargeOrderBO.setIdCard(medicalDetail.getIdCard());
        chargeOrderBO.setAgeYear(medicalDetail.getAgeYear());
        chargeOrderBO.setAgeMonth(medicalDetail.getAgeMonth());
        chargeOrderBO.setWeight(medicalDetail.getWeight());
        chargeOrderBO.setSystolicBp(medicalDetail.getSystolicBp());
        chargeOrderBO.setDiastolicBp(medicalDetail.getDiastolicBp());
        chargeOrderBO.setDoctorId(medicalDetail.getDoctorId());
        chargeOrderBO.setDoctorName(medicalDetail.getDoctorName());
        chargeOrderBO.setCreateUserId(createUserId);
        chargeOrderBO.setCreateBy(createBy);
        chargeOrderBO.setClinicId(medicalDetail.getClinicId());
        // 所有收费项目
        List<ChargeOrderItem> itemList = new ArrayList<>();
        AtomicInteger totalAmount = new AtomicInteger(CommonConstant.DEFAULT_0);
        // 处理各类收费项目
        handleExamList(medicalDetail.getExamList(), itemList, totalAmount,orderEmp);
        // 初始化 4 个不同类型的列表
        List<RxDrug> drugList = new ArrayList<>();
        List<RxInfusion> infusionList = new ArrayList<>();
        List<RxExt> extList = new ArrayList<>();
        List<RxTcm> tcmList = new ArrayList<>();
        // 单次遍历
        for (RxBase rxBase : medicalDetail.getRxList()) {
            // 根据 rxType 类型添加到对应的列表中
            if (RxTypeEnum.DRUG.getValue().equals(rxBase.getRxType())) {
                drugList.add((RxDrug) rxBase);
            } else if (RxTypeEnum.INFUSION.getValue().equals(rxBase.getRxType())) {
                infusionList.add((RxInfusion) rxBase);
            } else if (RxTypeEnum.EXT.getValue().equals(rxBase.getRxType())) {
                extList.add((RxExt) rxBase);
            } else if (RxTypeEnum.TCM.getValue().equals(rxBase.getRxType())) {
                tcmList.add((RxTcm) rxBase);
            }
        }
        handleDrugList(drugList, itemList, totalAmount,orderEmp);
        handleInfusionList(infusionList, itemList, totalAmount,orderEmp);
        handleTcmList(tcmList, itemList, totalAmount,orderEmp);
        handleExtList(extList, itemList, totalAmount,orderEmp);
        chargeOrderBO.setTotalAmount(totalAmount.intValue());
        chargeOrderBO.setItemList(itemList);
//        //如果病历的相关单子都是已支付的状态
//        if(CollectionUtils.isEmpty(itemList)){
//            return;
//        }
        createOrder(chargeOrderBO,ChargeOrderItemTypeEnum.getMedicalTypeList());
    }

    public void handleExtList(List<RxExt> extList, List<ChargeOrderItem> itemList, AtomicInteger totalAmount,ClinicEmpSimple orderEmp) {
        if(CollectionUtils.isEmpty(extList)){
            return;
        }
        for(RxExt rxExt : extList){
            if(PayStatusEnum.PAID.getValue().equals(rxExt.getPayStatus())){
                continue;
            }
            RxExtInfo extInfo = rxExt.getExtInfo();
            if(extInfo == null){
                continue;
            }
            // 创建收费明细
            OrderItemDetail itemDetail = new OrderItemDetail();
            itemDetail.setDetailId(extInfo.getProjectId());
            itemDetail.setDetailName(extInfo.getProjectName());
            itemDetail.setPrice(extInfo.getPrice());
            itemDetail.setTotalOutQty(extInfo.getTotalOutQty());
            itemDetail.setTotalOutQtyUnit(extInfo.getTotalOutQtyUnit());
            itemDetail.setTotalOutQtyUnitText(extInfo.getTotalOutQtyUnitText());
            itemDetail.setSubtotal(rxExt.getTotalAmount());
            // 创建收费项目
            ChargeOrderItem item = new ChargeOrderItem();
            item.setItemType(ChargeOrderItemTypeEnum.EXT.getValue());
            item.setItemRefId(rxExt.getRxId());
            item.setItemRefName(rxExt.getRxName());
            item.setOrderUserId(orderEmp.getEmpId());
            item.setOrderBy(orderEmp.getEmpName());
            item.setDeptId(orderEmp.getDeptId());
            item.setDeptName(orderEmp.getDeptName());
            item.setOrderTime(new Date());
            item.setSubtotal(rxExt.getTotalAmount());
            item.setDetailListJson(JsonUtil.obj2Json(Collections.singletonList(itemDetail)));
            itemList.add(item);
            totalAmount.addAndGet(item.getSubtotal());
        }
    }

    /**
     * 处理中药处方
     * @param tcmList
     * @param itemList
     * @param totalAmount
     */
    public void handleTcmList(List<RxTcm> tcmList, List<ChargeOrderItem> itemList, AtomicInteger totalAmount,ClinicEmpSimple orderEmp) {
        if(CollectionUtils.isEmpty(tcmList)){
            return;
        }
        for(RxTcm rxTcm : tcmList){
            if(PayStatusEnum.PAID.getValue().equals(rxTcm.getPayStatus())){
                continue;
            }
            RxTcmInfo rxTcmInfo = rxTcm.getTcmInfo();
            if(rxTcmInfo == null){
                continue;
            }
            List<RxTcmDetail> detailList = rxTcmInfo.getDetailList();
            List<OrderItemDetail> orderItemDetails = new ArrayList<>();
            for(RxTcmDetail rxTcmDetail: detailList){
                OrderItemDetail itemDetail = new OrderItemDetail();
                itemDetail.setDetailId(rxTcmDetail.getDrugId());
                itemDetail.setDetailName(rxTcmDetail.getDrugName());
                if(YesOrNoEnum.YES.getValue().equals(rxTcmDetail.getIsSplit())){
                    itemDetail.setPrice(rxTcmDetail.getSplitPrice());
                }else {
                    itemDetail.setPrice(rxTcmDetail.getPrice());
                }
                itemDetail.setTotalOutQty(rxTcmDetail.getTotalOutQty());
                itemDetail.setTotalOutQtyUnit(rxTcmDetail.getTotalOutQtyUnit());
                itemDetail.setTotalOutQtyUnitText(rxTcmDetail.getTotalOutQtyUnitText());
                itemDetail.setSubtotal(rxTcmDetail.getSubtotal());
                orderItemDetails.add(itemDetail);
            }
            // 创建收费项目
            ChargeOrderItem item = new ChargeOrderItem();
            item.setItemType(ChargeOrderItemTypeEnum.TCM.getValue());
            item.setItemRefId(rxTcm.getRxId());
            item.setItemRefName(rxTcm.getRxName());
            item.setOrderUserId(orderEmp.getEmpId());
            item.setOrderBy(orderEmp.getEmpName());
            item.setDeptId(orderEmp.getDeptId());
            item.setDeptName(orderEmp.getDeptName());
            item.setOrderTime(new Date());
            item.setSubtotal(rxTcm.getTotalAmount());
            item.setDetailListJson(JsonUtil.obj2Json(orderItemDetails));
            itemList.add(item);
            totalAmount.addAndGet(item.getSubtotal());
        }
    }

    /**
     * 处理输液处方
     * @param infusionList
     * @param itemList
     * @param totalAmount
     */
    public void handleInfusionList(List<RxInfusion> infusionList, List<ChargeOrderItem> itemList, AtomicInteger totalAmount,ClinicEmpSimple orderEmp) {
        if(CollectionUtils.isEmpty(infusionList)){
            return;
        }
        for(RxInfusion rxInfusion : infusionList){
            if(PayStatusEnum.PAID.getValue().equals(rxInfusion.getPayStatus())){
                continue;
            }
            List<RxInfusionGroup> groupList = rxInfusion.getGroupList();
            if(CollectionUtils.isEmpty(groupList)){
                continue;
            }
            List<OrderItemDetail> orderItemDetails = new ArrayList<>();
            for(RxInfusionGroup rxInfusionGroup : groupList){
                List<RxInfusionGroupDetail> detailList = rxInfusionGroup.getDetailList();
                if(CollectionUtils.isEmpty(detailList)){
                    continue;
                }
                for(RxInfusionGroupDetail detailVo : detailList){
                    // 创建收费明细
                    OrderItemDetail itemDetail = new OrderItemDetail();
                    itemDetail.setDetailId(detailVo.getDrugId());
                    itemDetail.setDetailName(detailVo.getDrugName());
                    if(YesOrNoEnum.YES.getValue().equals(detailVo.getIsSplit())){
                        itemDetail.setPrice(detailVo.getSplitPrice());
                    }else {
                        itemDetail.setPrice(detailVo.getPrice());
                    }
                    itemDetail.setTotalOutQty(detailVo.getTotalOutQty());
                    itemDetail.setTotalOutQtyUnit(detailVo.getTotalOutQtyUnit());
                    itemDetail.setTotalOutQtyUnitText(detailVo.getTotalOutQtyUnitText());
                    itemDetail.setSubtotal(detailVo.getSubtotal());
                    orderItemDetails.add(itemDetail);
                }
            }
            // 创建收费项目
            ChargeOrderItem item = new ChargeOrderItem();
            item.setItemType(ChargeOrderItemTypeEnum.INFUSION.getValue());
            item.setItemRefId(rxInfusion.getRxId());
            item.setItemRefName(rxInfusion.getRxName());
            item.setOrderUserId(orderEmp.getEmpId());
            item.setOrderBy(orderEmp.getEmpName());
            item.setDeptId(orderEmp.getDeptId());
            item.setDeptName(orderEmp.getDeptName());
            item.setOrderTime(new Date());
            item.setSubtotal(rxInfusion.getTotalAmount());
            item.setDetailListJson(JsonUtil.obj2Json(orderItemDetails));
            itemList.add(item);
            totalAmount.addAndGet(item.getSubtotal());
        }
    }

    /**
     * 处理成药处方
     * @param drugList
     * @param itemList
     * @param totalAmount
     */
    public void handleDrugList(List<RxDrug> drugList, List<ChargeOrderItem> itemList, AtomicInteger totalAmount,ClinicEmpSimple orderEmp) {
        if(CollectionUtils.isEmpty(drugList)){
            return;
        }
        for(RxDrug rxDrug : drugList){
            if(PayStatusEnum.PAID.getValue().equals(rxDrug.getPayStatus())){
                continue;
            }
            List<RxDrugDetail> detailList = rxDrug.getDetailList();
            if(CollectionUtils.isEmpty(detailList)){
                continue;
            }
            List<OrderItemDetail> orderItemDetails = new ArrayList<>();
            for(RxDrugDetail rxDrugDetail : detailList){
                // 创建收费明细
                OrderItemDetail itemDetail = new OrderItemDetail();
                itemDetail.setDetailId(rxDrugDetail.getDrugId());
                itemDetail.setDetailName(rxDrugDetail.getDrugName());
                if(YesOrNoEnum.YES.getValue().equals(rxDrugDetail.getIsSplit())){
                    itemDetail.setPrice(rxDrugDetail.getSplitPrice());
                }else {
                    itemDetail.setPrice(rxDrugDetail.getPrice());
                }
                itemDetail.setTotalOutQty(rxDrugDetail.getTotalOutQty());
                itemDetail.setTotalOutQtyUnit(rxDrugDetail.getTotalOutQtyUnit());
                itemDetail.setTotalOutQtyUnitText(rxDrugDetail.getTotalOutQtyUnitText());
                itemDetail.setSubtotal(rxDrugDetail.getSubtotal());
                orderItemDetails.add(itemDetail);
            }
            // 创建收费项目
            ChargeOrderItem item = new ChargeOrderItem();
            item.setItemType(ChargeOrderItemTypeEnum.DRUG.getValue());
            item.setItemRefId(rxDrug.getRxId());
            item.setItemRefName(rxDrug.getRxName());
            item.setOrderUserId(orderEmp.getEmpId());
            item.setOrderBy(orderEmp.getEmpName());
            item.setDeptId(orderEmp.getDeptId());
            item.setDeptName(orderEmp.getDeptName());
            item.setOrderTime(new Date());
            item.setSubtotal(rxDrug.getTotalAmount());
            item.setDetailListJson(JsonUtil.obj2Json(orderItemDetails));
            itemList.add(item);
            totalAmount.addAndGet(item.getSubtotal());
        }
    }

    /**
     * 处理查验项目
     * @param examList
     * @param itemList
     * @param totalAmount
     */
    public void handleExamList(List<ExamDetail> examList, List<ChargeOrderItem> itemList, AtomicInteger totalAmount,ClinicEmpSimple orderEmp) {
        if(CollectionUtils.isEmpty(examList)){
            return;
        }
        for(ExamDetail examDetail : examList){
            if(PayStatusEnum.PAID.getValue().equals(examDetail.getPayStatus())){
                continue;
            }
            // 创建收费明细
            OrderItemDetail itemDetail = new OrderItemDetail();
            itemDetail.setDetailId(examDetail.getProjectId());
            itemDetail.setDetailName(examDetail.getProjectName());
            itemDetail.setPrice(examDetail.getPrice());
            itemDetail.setTotalOutQty(examDetail.getTotalOutQty());
            itemDetail.setTotalOutQtyUnit(examDetail.getTotalOutQtyUnit());
            itemDetail.setTotalOutQtyUnitText(examDetail.getTotalOutQtyUnitText());
            itemDetail.setSubtotal(examDetail.getSubtotal());
            // 创建收费项目
            ChargeOrderItem item = new ChargeOrderItem();
            if(ProjectCategoryEnum.EXAM.getValue().equals(examDetail.getProjectCategory())){
                item.setItemType(ChargeOrderItemTypeEnum.EXAM.getValue());
            }else {
                item.setItemType(ChargeOrderItemTypeEnum.LAB.getValue());
            }
            item.setItemRefId(examDetail.getExamId());
            item.setItemRefName(ProjectCategoryEnum.getText(examDetail.getProjectCategory()));
            item.setOrderUserId(orderEmp.getEmpId());
            item.setOrderBy(orderEmp.getEmpName());
            item.setDeptId(orderEmp.getDeptId());
            item.setDeptName(orderEmp.getDeptName());
            item.setOrderTime(new Date());
            item.setSubtotal(examDetail.getSubtotal());
            item.setDetailListJson(JsonUtil.obj2Json(Collections.singletonList(itemDetail)));
            itemList.add(item);
            totalAmount.addAndGet(item.getSubtotal());
        }
    }


    /**
     * 添加输液费
     * @param addInfusionFee
     */
    @Transactional(rollbackFor = Exception.class)
    public ChargeOrderBO addInfusionFee(OrderExec orderExec,AddInfusionFeeDTO addInfusionFee) {
        // 获取创建人信息（根据挂号方式判断）
        ClinicEmpSimple orderEmp = clinicEmpService.getEmpSimple(addInfusionFee.getClinicId(),addInfusionFee.getUserId());
        // 创建收费明细
        OrderItemDetail itemDetail = new OrderItemDetail();
        itemDetail.setDetailId(addInfusionFee.getOrderId());
        itemDetail.setDetailName(ChargeOrderItemTypeEnum.INFUSION_FEE.getText());
        itemDetail.setPrice(addInfusionFee.getAmount());
        itemDetail.setTotalOutQty(CommonConstant.DEFAULT_1);
        itemDetail.setTotalOutQtyUnit(UnitConstant.ci);
        itemDetail.setTotalOutQtyUnitText(UnitConstant.ci_en);
        itemDetail.setSubtotal(addInfusionFee.getAmount());
        // 创建收费项目
        ChargeOrderItem item = new ChargeOrderItem();
        item.setItemType(ChargeOrderItemTypeEnum.INFUSION_FEE.getValue());
        item.setItemRefId(addInfusionFee.getOrderId());
        item.setItemRefName(ChargeOrderItemTypeEnum.INFUSION_FEE.getText());
        item.setOrderUserId(orderEmp.getEmpId());
        item.setOrderBy(orderEmp.getEmpName());
        item.setDeptId(orderEmp.getDeptId());
        item.setDeptName(orderEmp.getDeptName());
        item.setOrderTime(new Date());
        item.setSubtotal(addInfusionFee.getAmount());
        item.setDetailListJson(JsonUtil.obj2Json(Collections.singletonList(itemDetail)));
        // 创建收费单
        ChargeOrderBO chargeOrderBO = new ChargeOrderBO();
        chargeOrderBO.setVisitNo(orderExec.getVisitNo());
        chargeOrderBO.setVisitDate(orderExec.getVisitDate());
        chargeOrderBO.setPatientId(orderExec.getPatientId());
        chargeOrderBO.setPatientName(orderExec.getPatientName());
        chargeOrderBO.setPatientGender(orderExec.getPatientGender());
        chargeOrderBO.setPatientPhone(orderExec.getPatientPhone());
        chargeOrderBO.setIdCard(orderExec.getIdCard());
        chargeOrderBO.setAgeYear(orderExec.getAgeYear());
        chargeOrderBO.setAgeMonth(orderExec.getAgeMonth());
        chargeOrderBO.setWeight(orderExec.getWeight());
        chargeOrderBO.setSystolicBp(orderExec.getSystolicBp());
        chargeOrderBO.setDiastolicBp(orderExec.getDiastolicBp());
        chargeOrderBO.setCreateUserId(orderEmp.getEmpId());
        chargeOrderBO.setCreateBy(orderEmp.getEmpName());
        chargeOrderBO.setDoctorId(orderExec.getDoctorId());
        chargeOrderBO.setDoctorName(orderExec.getDoctorName());
        chargeOrderBO.setTotalAmount(addInfusionFee.getAmount());
        chargeOrderBO.setClinicId(orderExec.getClinicId());
        chargeOrderBO.setItemList(Collections.singletonList(item));
        return createOrder(chargeOrderBO,ChargeOrderItemTypeEnum.getInfusionTypeList());
    }

    /**
     * 挂号收费单
     * @param clinicRegister
     */
    @Transactional(rollbackFor = Exception.class)
    public ChargeOrderBO createRegisterOrder(ClinicRegister clinicRegister) {
        // 获取创建人信息（根据挂号方式判断）
        ClinicEmpSimple orderEmp = clinicEmpService.getEmpSimple(clinicRegister.getClinicId(),clinicRegister.getCreateUserId());
        // 创建收费明细
        OrderItemDetail itemDetail = new OrderItemDetail();
        itemDetail.setDetailId(clinicRegister.getRegisterId());
        itemDetail.setDetailName(ChargeOrderItemTypeEnum.REGISTER.getText());
        itemDetail.setPrice(clinicRegister.getRegFee());
        itemDetail.setTotalOutQty(CommonConstant.DEFAULT_1);
        itemDetail.setTotalOutQtyUnit(UnitConstant.ci);
        itemDetail.setTotalOutQtyUnitText(UnitConstant.ci_en);
        itemDetail.setSubtotal(clinicRegister.getRegFee());
        // 创建收费项目
        ChargeOrderItem item = new ChargeOrderItem();
        item.setItemType(ChargeOrderItemTypeEnum.REGISTER.getValue());
        item.setItemRefId(clinicRegister.getRegisterId());
        item.setItemRefName(ChargeOrderItemTypeEnum.REGISTER.getText());
        item.setOrderUserId(orderEmp.getEmpId());
        item.setOrderBy(orderEmp.getEmpName());
        item.setDeptId(orderEmp.getDeptId());
        item.setDeptName(orderEmp.getDeptName());
        item.setOrderTime(new Date());
        item.setSubtotal(clinicRegister.getRegFee());
        item.setDetailListJson(JsonUtil.obj2Json(Collections.singletonList(itemDetail)));
        // 创建收费单
        ChargeOrderBO chargeOrderBO = new ChargeOrderBO();
        chargeOrderBO.setVisitNo(clinicRegister.getVisitNo());
        chargeOrderBO.setVisitDate(clinicRegister.getVisitDate());
        chargeOrderBO.setPatientId(clinicRegister.getPatientId());
        chargeOrderBO.setPatientName(clinicRegister.getPatientName());
        chargeOrderBO.setPatientGender(clinicRegister.getPatientGender());
        chargeOrderBO.setPatientPhone(clinicRegister.getPatientPhone());
        chargeOrderBO.setIdCard(clinicRegister.getIdCard());
        chargeOrderBO.setAgeYear(clinicRegister.getAgeYear());
        chargeOrderBO.setAgeMonth(clinicRegister.getAgeMonth());
        chargeOrderBO.setWeight(clinicRegister.getWeight());
        chargeOrderBO.setSystolicBp(clinicRegister.getSystolicBp());
        chargeOrderBO.setDiastolicBp(clinicRegister.getDiastolicBp());
        chargeOrderBO.setDoctorId(clinicRegister.getDoctorId());
        chargeOrderBO.setDoctorName(clinicRegister.getDoctorName());
        chargeOrderBO.setCreateUserId(orderEmp.getEmpId());
        chargeOrderBO.setCreateBy(orderEmp.getEmpName());
        chargeOrderBO.setTotalAmount(clinicRegister.getRegFee());
        chargeOrderBO.setClinicId(clinicRegister.getClinicId());
        chargeOrderBO.setItemList(Collections.singletonList(item));
        return createOrder(chargeOrderBO,ChargeOrderItemTypeEnum.getRegisterTypeList());
    }

    /**
     * 下单
     */
    @Transactional(rollbackFor = Exception.class)
    public ChargeOrderBO createOrder(ChargeOrderBO chargeOrderBO,List<String> types){
        validateCharge(chargeOrderBO);
        //根据诊号和日期查询是否存在已有的订单
        ChargeOrder dbChargeOrder = getOrderByVisitNo(chargeOrderBO.getVisitNo(),chargeOrderBO.getVisitDate());
        if(dbChargeOrder == null){
            return addOrder(chargeOrderBO);
        }else {
            dbChargeOrder.setPatientName(chargeOrderBO.getPatientName());
            dbChargeOrder.setPatientGender(chargeOrderBO.getPatientGender());
            dbChargeOrder.setPatientPhone(chargeOrderBO.getPatientPhone());
            dbChargeOrder.setIdCard(chargeOrderBO.getIdCard());
            dbChargeOrder.setAgeYear(chargeOrderBO.getAgeYear());
            dbChargeOrder.setAgeMonth(chargeOrderBO.getAgeMonth());
            dbChargeOrder.setWeight(chargeOrderBO.getWeight());
            dbChargeOrder.setSystolicBp(chargeOrderBO.getSystolicBp());
            dbChargeOrder.setDiastolicBp(chargeOrderBO.getDiastolicBp());
            dbChargeOrder.setUpdateUserId(chargeOrderBO.getCreateUserId());
            dbChargeOrder.setUpdateBy(chargeOrderBO.getCreateBy());
            updateOrder(dbChargeOrder,types,chargeOrderBO.getItemList());
            chargeOrderBO.setOrderId(dbChargeOrder.getOrderId());
        }
       return chargeOrderBO;
    }

    /**
     * 根据诊号获取订单
     * @param visitNo
     * @param visitDate
     * @return
     */
    public ChargeOrder getOrderByVisitNo(String visitNo,LocalDate visitDate){
        ChargeOrderExample example = new ChargeOrderExample();
        ChargeOrderExample.Criteria criteria = example.createCriteria();
        criteria.andVisitNoEqualTo(visitNo);
        criteria.andVisitDateEqualTo(visitDate);
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        List<ChargeOrder> orderList = chargeOrderMapper.selectByExample(example);
        return CollectionUtils.isEmpty(orderList) ? null : orderList.get(0);
    }


    /**
     * 修改订单
     * @param chargeOrder
     * @param types 明细类型
     * @param itemList 明细
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateOrder(ChargeOrder chargeOrder,List<String> types,List<ChargeOrderItem> itemList) {
        //根据类型获取未支付的项目
        Integer orderedAmount = CommonConstant.DEFAULT_0;
        if(!ChargeOrderItemTypeEnum.INFUSION_FEE.getValue().equals(types.get(0))){
            //输液项目累加
            List<Long> orderedItemIdList = new ArrayList();
            List<ChargeOrderItem> dbItemList = getOrderItemList(chargeOrder.getOrderId(),types);
            if(!CollectionUtils.isEmpty(dbItemList)){
                for(ChargeOrderItem chargeOrderItem : dbItemList){
                    if(PayStatusEnum.ORDERED.getValue().equals(chargeOrderItem.getPayStatus())){
                        orderedItemIdList.add(chargeOrderItem.getItemId());
                        orderedAmount = orderedAmount + chargeOrderItem.getSubtotal();
                    }
                }
            }
            //先删除未支付的项目
            if(!CollectionUtils.isEmpty(orderedItemIdList)){
                deleteOrderItemByIdList(orderedItemIdList,chargeOrder.getUpdateUserId(),chargeOrder.getUpdateBy());
            }
        }
        Integer addTotalAmount = CommonConstant.DEFAULT_0;
        if(!CollectionUtils.isEmpty(itemList)){
            //保存新增的支付项
            addTotalAmount = addOrderItemBatch(chargeOrder.getClinicId(),chargeOrder.getOrderId(),chargeOrder.getUpdateUserId(),chargeOrder.getUpdateBy(),itemList);
        }
        //更新下单时间
        chargeOrder.setOrderTime(new Date());
        long orderedCount = getOrderedCount(chargeOrder.getOrderId());
        if(orderedCount == 0){
            chargeOrder.setPayStatus(PayStatusEnum.PAID.getValue());
        }else {
            chargeOrder.setPayStatus(PayStatusEnum.ORDERED.getValue());
        }
        chargeOrder.setTotalAmount(chargeOrder.getTotalAmount() + addTotalAmount - orderedAmount);
        chargeOrder.setUpdateTime(new Date());
        chargeOrderMapper.updateByPrimaryKeySelective(chargeOrder);
    }

    /**
     * 查询指定订单的收费明细项
     * @param orderId 订单ID
     * @return 明细项列表
     */
    public long getOrderedCount(Long orderId) {
        ChargeOrderItemExample example = new ChargeOrderItemExample();
        ChargeOrderItemExample.Criteria criteria = example.createCriteria();
        criteria.andOrderIdEqualTo(orderId);
        criteria.andPayStatusEqualTo(PayStatusEnum.ORDERED.getValue());
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        return chargeOrderItemMapper.countByExample(example);
    }




    /**
     * 删除所有未支付的项目
     * @param orderedItemIdList
     * @param updateUserId
     * @param updateBy
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteOrderItemByIdList(List<Long> orderedItemIdList,Long updateUserId,String updateBy) {
        ChargeOrderItemExample example = new ChargeOrderItemExample();
        ChargeOrderItemExample.Criteria criteria = example.createCriteria();
        criteria.andItemIdIn(orderedItemIdList);
        ChargeOrderItem chargeOrderItem = new ChargeOrderItem();
        chargeOrderItem.setUpdateUserId(updateUserId);
        chargeOrderItem.setUpdateBy(updateBy);
        chargeOrderItem.setIsDelete(YesOrNoEnum.YES.getValue());
        chargeOrderItemMapper.updateByExampleSelective(chargeOrderItem,example);
    }


    /**
     * 保存订单
     * @param chargeOrderBO
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public ChargeOrderBO addOrder(ChargeOrderBO chargeOrderBO) {
        chargeOrderBO.setOrderNo(IdBuilder.getUniqueId("R"));
        chargeOrderBO.setOrderTime(new Date());
        chargeOrderBO.setPayStatus(PayStatusEnum.ORDERED.getValue());
        chargeOrderBO.setSortNum(CommonConstant.DEFAULT_1);
        chargeOrderBO.setIsEnabled(YesOrNoEnum.YES.getValue());
        chargeOrderBO.setIsDelete(YesOrNoEnum.NO.getValue());
        chargeOrderBO.setCreateTime(new Date());
        chargeOrderMapper.insertSelective(chargeOrderBO);
        addOrderItemBatch(chargeOrderBO.getClinicId(),chargeOrderBO.getOrderId(),chargeOrderBO.getCreateUserId(),chargeOrderBO.getCreateBy(),chargeOrderBO.getItemList());
        return chargeOrderBO;
    }




    /**
     * 批量添加收费项目
     */
    @Transactional(rollbackFor = Exception.class)
    public Integer addOrderItemBatch(Long clinicId,Long orderId,Long createUserId,String createBy,List<ChargeOrderItem> itemList){
        Date now = new Date();
        Integer totalAmount = CommonConstant.DEFAULT_0;
        for (ChargeOrderItem item : itemList) {
            item.setOrderId(orderId);
            item.setPayStatus(PayStatusEnum.ORDERED.getValue());
            item.setSortNum(CommonConstant.DEFAULT_1);
            item.setClinicId(clinicId);
            item.setIsEnabled(YesOrNoEnum.YES.getValue());
            item.setIsDelete(YesOrNoEnum.NO.getValue());
            item.setCreateUserId(createUserId);
            item.setCreateBy(createBy);
            item.setCreateTime(now);
            totalAmount = totalAmount + item.getSubtotal();
        }
        //保存订单项目
        specChargeOrderMapper.addOrderItemBatch(itemList);
        return totalAmount;
    }


    /**
     * 校验订单信息
     * @param chargeOrderBO
     */
    public void validateCharge(ChargeOrderBO chargeOrderBO) {
        // 核心字段校验
        if (StringUtil.isBlank(chargeOrderBO.getVisitNo())) {
            throw new BusinessFailException("诊号不能为空");
        }
        if (StringUtil.isBlank(chargeOrderBO.getPatientId())) {
            throw new BusinessFailException("患者信息不能为空");
        }
        // 收费项目校验
        List<ChargeOrderItem> itemList = chargeOrderBO.getItemList();
        if(CollectionUtils.isEmpty(itemList)){
            return;
        }
        // 校验总金额
        if (chargeOrderBO.getTotalAmount() == null || chargeOrderBO.getTotalAmount() <= CommonConstant.DEFAULT_0) {
            throw new BusinessFailException("订单金额必须大于" + CommonConstant.DEFAULT_0);
        }
        for (ChargeOrderItem item : itemList) {
            if (StringUtil.isBlank(item.getItemType())) {
                throw new BusinessFailException("收费项目类型不能为空");
            }
            if (!ChargeOrderItemTypeEnum.isValue(item.getItemType())) {
                throw new BusinessFailException("收费项目类型错误");
            }
            if (StringUtil.isBlank(item.getItemRefId()) || StringUtil.isBlank(item.getItemRefName())) {
                throw new BusinessFailException("收费项目不能为空");
            }
            if (item.getSubtotal() == null || item.getSubtotal() <= CommonConstant.DEFAULT_0) {
                throw new BusinessFailException("订单金额必须大于" + CommonConstant.DEFAULT_0);
            }
        }
    }

    /**
     *
     * @param orderId
     * @return
     */
    public ChargeOrder getOrderById(Long orderId){
        if(StringUtil.isBlank(orderId)){
            return null;
        }
        ChargeOrder chargeOrder = chargeOrderMapper.selectByPrimaryKey(orderId);
        if(chargeOrder == null || YesOrNoEnum.YES.getValue().equals(chargeOrder.getIsDelete())){
            return null;
        }
        return chargeOrder;
    }


    public ChargeOrderRecord getChargeOrderRecordById(Long recordId){
        if(StringUtil.isBlank(recordId)){
            return null;
        }
        ChargeOrderRecord chargeOrderRecord = chargeOrderRecordMapper.selectByPrimaryKey(recordId);
        if(chargeOrderRecord == null || YesOrNoEnum.YES.getValue().equals(chargeOrderRecord.getIsDelete())){
            return null;
        }
        return chargeOrderRecord;
    }

    /**
     * 缴费
     * @param orderPayDTO 支付信息 DTO
     */
    @Transactional(rollbackFor = Exception.class)
    public Long doCharge(OrderPayDTO orderPayDTO){
        // 查询订单
        ChargeOrder dbChargeOrder = getOrderById(orderPayDTO.getOrderId());
        if (dbChargeOrder == null) {
            throw new BusinessFailException("订单不存在");
        }
        // 校验订单状态是否可支付
        if (!PayStatusEnum.isPay(dbChargeOrder.getPayStatus())) {
            throw new BusinessFailException("订单状态不允许支付");
        }
        // 获取当前订单下的所有收费项目
        List<ChargeOrderItem> orderItemList = getOrderItemList(orderPayDTO.getOrderId(),null);
        if (CollectionUtils.isEmpty(orderItemList)) {
            throw new BusinessFailException("没有找到支付明细项目");
        }
        // 按 payStatus 分组
        Map<String, List<ChargeOrderItem>> payMap = orderItemList.stream()
                .collect(Collectors.groupingBy(ChargeOrderItem::getPayStatus));
        // 已经支付的项目
        List<ChargeOrderItem> paidList = payMap.getOrDefault(PayStatusEnum.PAID.getValue(), Collections.emptyList());
        // 还没有支付的项目
        List<ChargeOrderItem> orderedList = payMap.getOrDefault(PayStatusEnum.ORDERED.getValue(), Collections.emptyList());
        // 如果所有项目都已支付，拒绝再次支付
        if (!paidList.isEmpty() && paidList.size() == orderItemList.size()) {
            throw new BusinessFailException("订单已完成支付");
        }
        // 构建要支付的收费项目列表（完整实体）
        List<ChargeOrderItem> toBePaidItemList;
        String finalPayStatus = PayStatusEnum.ORDERED.getValue();
        if (CollectionUtils.isEmpty(orderPayDTO.getItemIdList())) {
            // 全部支付
            toBePaidItemList = orderedList;
            //全部支付的状态
            finalPayStatus = PayStatusEnum.PAID.getValue();
        } else {
            // 部分支付：只支付在 itemIdList 里的项
            Set<Long> requestedItemIds = new HashSet<>(orderPayDTO.getItemIdList());
            toBePaidItemList = orderedList.stream()
                    .filter(item -> requestedItemIds.contains(item.getItemId()))
                    .collect(Collectors.toList());
            Set<Long> orderedItemIds = orderedList.stream()
                    .map(ChargeOrderItem::getItemId)
                    .collect(Collectors.toSet());
            boolean isAllOrderedItemPaid = requestedItemIds.equals(orderedItemIds);
            if (isAllOrderedItemPaid) {
                finalPayStatus = PayStatusEnum.PAID.getValue();
            }
        }
        /**
         * 总的支付金额
         */
        if(PayChannelEnum.MEMBER.getValue().equals(orderPayDTO.getPayChannel())){
            //如果是会员卡支付，扣减会员卡余额
            MemberConsumeDTO memberConsumeDTO = new MemberConsumeDTO();
            memberConsumeDTO.setPatientId(dbChargeOrder.getPatientId());
            memberConsumeDTO.setAmount(toBePaidItemList.stream()
                    .filter(Objects::nonNull)
                    .map(ChargeOrderItem::getSubtotal)
                    .filter(Objects::nonNull)
                    .mapToInt(Integer::intValue)
                    .sum());
            memberConsumeDTO.setClinicId(dbChargeOrder.getClinicId());
            memberConsumeDTO.setOrderNo(dbChargeOrder.getOrderNo());
            memberConsumeDTO.setCreateUserId(orderPayDTO.getChargeUserId());
            memberConsumeDTO.setCreateBy(orderPayDTO.getChargeBy());
            memberService.consume(memberConsumeDTO);
        }
        // 当前时间
        Date now = new Date();
        // 执行订单项状态更新
        updateOrderItemBatch(toBePaidItemList, orderPayDTO, now);
        // 更新订单状态和元信息
        dbChargeOrder.setPayStatus(finalPayStatus);
        dbChargeOrder.setPayTime(now);
        dbChargeOrder.setUpdateUserId(orderPayDTO.getChargeUserId());
        dbChargeOrder.setUpdateBy(orderPayDTO.getChargeBy());
        dbChargeOrder.setUpdateTime(now);
        chargeOrderMapper.updateByPrimaryKeySelective(dbChargeOrder);
        //保存收费记录
        Long recordId = addChargeOrderRecord(orderPayDTO,toBePaidItemList);
        //支付支付完成后的动作
        handlePayment(dbChargeOrder,orderPayDTO,toBePaidItemList);
        return recordId;
    }

    /**
     * 保存收费记录
     * @param orderPayDTO
     * @param toBePaidItemList
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Long addChargeOrderRecord(OrderPayDTO orderPayDTO,List<ChargeOrderItem> toBePaidItemList) {
        Integer totalAmount = toBePaidItemList.stream()
                .filter(Objects::nonNull)
                .map(ChargeOrderItem::getSubtotal)
                .filter(Objects::nonNull)
                .mapToInt(Integer::intValue)
                .sum();
        ChargeOrderRecord chargeOrderRecord = new ChargeOrderRecord();
        chargeOrderRecord.setOrderId(orderPayDTO.getOrderId());
        chargeOrderRecord.setItemIds(toBePaidItemList.stream()
                .map(item -> String.valueOf(item.getItemId()))
                .collect(Collectors.joining(",")));
        chargeOrderRecord.setTotalAmount(totalAmount);
        chargeOrderRecord.setPaidAmount(totalAmount);
        chargeOrderRecord.setPayChannel(orderPayDTO.getPayChannel());
        chargeOrderRecord.setChargeUserId(orderPayDTO.getChargeUserId());
        chargeOrderRecord.setChargeBy(orderPayDTO.getChargeBy());
        chargeOrderRecord.setChargeTime(new Date());
        chargeOrderRecord.setDetailListJson(getOrderRecordDetailList(toBePaidItemList));
        chargeOrderRecord.setClinicId(orderPayDTO.getClinicId());
        chargeOrderRecord.setIsEnabled(YesOrNoEnum.YES.getValue());
        chargeOrderRecord.setIsDelete(YesOrNoEnum.NO.getValue());
        chargeOrderRecord.setCreateUserId(chargeOrderRecord.getChargeUserId());
        chargeOrderRecord.setCreateBy(chargeOrderRecord.getChargeBy());
        chargeOrderRecord.setCreateTime(chargeOrderRecord.getChargeTime());
        chargeOrderRecordMapper.insertSelective(chargeOrderRecord);
        return chargeOrderRecord.getRecordId();
    }

    public String getOrderRecordDetailList(List<ChargeOrderItem> toBePaidItemList) {
        List<ChargeOrderRecordDetail> orderRecordDetailList = new ArrayList<>();
        for(ChargeOrderItem chargeOrderItem : toBePaidItemList){
            if(ChargeOrderItemTypeEnum.EXAM.getValue().equals(chargeOrderItem.getItemType())
                    || ChargeOrderItemTypeEnum.LAB.getValue().equals(chargeOrderItem.getItemType())){
                //检查项目
                List<OrderItemDetail> detailList = JsonUtil.json2Obj(chargeOrderItem.getDetailListJson(), new TypeReference<List<OrderItemDetail>>() {});
                for(OrderItemDetail orderItemDetail : detailList){
                    ChargeOrderRecordDetail orderRecordDetail = new ChargeOrderRecordDetail();
                    orderRecordDetail.setItemName(orderItemDetail.getDetailName());
                    orderRecordDetail.setTotalOutQty(orderItemDetail.getTotalOutQty());
                    orderRecordDetail.setSubtotal(orderItemDetail.getSubtotal());
                    orderRecordDetailList.add(orderRecordDetail);
                }
            }else {
                ChargeOrderRecordDetail orderRecordDetail = new ChargeOrderRecordDetail();
                orderRecordDetail.setItemName(chargeOrderItem.getItemRefName());
                orderRecordDetail.setTotalOutQty(CommonConstant.DEFAULT_1);
                orderRecordDetail.setSubtotal(chargeOrderItem.getSubtotal());
                orderRecordDetailList.add(orderRecordDetail);
            }
        }
        return JsonUtil.obj2Json(orderRecordDetailList);
    }


    /**
     * 执行支付完成后的动作
     * @param dbChargeOrder
     * @param toBePaidItemList
     */
    @Transactional(rollbackFor = Exception.class)
    public void handlePayment(ChargeOrder dbChargeOrder, OrderPayDTO orderPayDTO,List<ChargeOrderItem> toBePaidItemList) {
        Long chargeUserId = orderPayDTO.getChargeUserId();
        String chargeBy = orderPayDTO.getChargeBy();
        String payChannel = orderPayDTO.getPayChannel();
        //统计诊所今日营收
        StatClinicIncomeDaily statClinicIncomeDaily = new StatClinicIncomeDaily();
        statClinicIncomeDaily.setClinicId(dbChargeOrder.getClinicId());
        statClinicIncomeDaily.setIncomeAmount(toBePaidItemList.stream()
                .map(ChargeOrderItem::getSubtotal)
                .filter(Objects::nonNull)
                .mapToInt(Integer::intValue)
                .sum());
        statClinicIncomeDaily.setIncomeCount(CommonConstant.DEFAULT_1);
        asyncTaskService.asyncSaveOrUpdateClinicIncome(statClinicIncomeDaily);
        Map<String, List<ChargeOrderItem>> itemTypeMap = toBePaidItemList.stream()
                .collect(Collectors.groupingBy(ChargeOrderItem::getItemType));
        //获取挂号项目
        List<ChargeOrderItem> registerList = itemTypeMap.get(ChargeOrderItemTypeEnum.REGISTER.getValue());
        if(!CollectionUtils.isEmpty(registerList)){
            ChargeOrderItem chargeOrderItem = registerList.get(0);
            //如果是挂号费，需要修改挂号单的状态为已支付
            ClinicRegister clinicRegister = new ClinicRegister();
            clinicRegister.setRegisterId(chargeOrderItem.getItemRefId());
            clinicRegister.setPayChannel(payChannel);
            clinicRegister.setUpdateUserId(chargeUserId);
            clinicRegister.setUpdateBy(chargeBy);
            registerService.paySuccess(clinicRegister);
        }
        //其他项目需要生成对应的单子
        List<ChargeOrderItem> allExamList = new ArrayList<>();
        //检查项目
        List<ChargeOrderItem> examList = itemTypeMap.get(ChargeOrderItemTypeEnum.EXAM.getValue());
        if(!CollectionUtils.isEmpty(examList)){
            allExamList.addAll(examList);
        }
        //检查项目
        List<ChargeOrderItem> labList = itemTypeMap.get(ChargeOrderItemTypeEnum.LAB.getValue());
        if(!CollectionUtils.isEmpty(labList)){
            allExamList.addAll(labList);
        }
        if(!CollectionUtils.isEmpty(allExamList)){
            //1.修改处方的收费状态
            List<Long> itemRefIdList = allExamList.stream()
                    .map(ChargeOrderItem::getItemRefId)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
            clinicMedicalService.updateExamListPayStatus(itemRefIdList);
            //2.开具对应的检查单
            orderExamService.createExam(dbChargeOrder,allExamList);
        }
        //修改处方状态
        List<ChargeOrderItem> allExamItemList = new ArrayList<>();
        //药品领用单
        List<ChargeOrderItem> allDispenseItemList = new ArrayList<>();
        //执行单
        List<ChargeOrderItem> allExecItemList = new ArrayList<>();
        //成药项目 开具药品领用单
        List<ChargeOrderItem> drugList = itemTypeMap.get(ChargeOrderItemTypeEnum.DRUG.getValue());
        if(!CollectionUtils.isEmpty(drugList)){
            allDispenseItemList.addAll(drugList);
            allExamItemList.addAll(drugList);
        }
        //输液项目 开具药品领用单+输液执行单
        List<ChargeOrderItem> infusionList = itemTypeMap.get(ChargeOrderItemTypeEnum.INFUSION.getValue());
        if(!CollectionUtils.isEmpty(infusionList)){
            allDispenseItemList.addAll(infusionList);
            allExamItemList.addAll(infusionList);
            allExecItemList.addAll(infusionList);
        }
        //中药项目 开具药品领用单
        List<ChargeOrderItem> tcmList = itemTypeMap.get(ChargeOrderItemTypeEnum.TCM.getValue());
        if(!CollectionUtils.isEmpty(tcmList)){
            allDispenseItemList.addAll(tcmList);
            allExamItemList.addAll(tcmList);
        }
        //外治项目 开具执行单
        List<ChargeOrderItem> extList = itemTypeMap.get(ChargeOrderItemTypeEnum.EXT.getValue());
        if(!CollectionUtils.isEmpty(extList)){
            allExamItemList.addAll(extList);
            allExecItemList.addAll(extList);
        }
        if(!CollectionUtils.isEmpty(allExamItemList)){
            //修改处方的订单状态
            List<Long> itemRefIdList = allExamItemList.stream()
                    .map(ChargeOrderItem::getItemRefId)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
            clinicMedicalService.updateRxListPayStatus(itemRefIdList);
        }
        if(!CollectionUtils.isEmpty(allDispenseItemList)){
            //开具对应的配药单
            orderDispenseService.createDispense(dbChargeOrder,allDispenseItemList);
        }
        if(!CollectionUtils.isEmpty(allExecItemList)){
            //开具执行单
            orderExecService.createExec(dbChargeOrder,allExecItemList);
        }
    }

    /**
     * 批量修改支付项状态
     * @param itemList 待更新项实体列表
     * @param orderPayDTO 支付数据
     * @param now 当前时间
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateOrderItemBatch(List<ChargeOrderItem> itemList, OrderPayDTO orderPayDTO, Date now) {
        if (CollectionUtils.isEmpty(itemList)) {
            return;
        }
        // 提取所有 itemId
        List<Long> itemIdList = itemList.stream()
                .map(ChargeOrderItem::getItemId)
                .collect(Collectors.toList());
        // 构造更新条件
        ChargeOrderItemExample example = new ChargeOrderItemExample();
        ChargeOrderItemExample.Criteria criteria = example.createCriteria();
        criteria.andItemIdIn(itemIdList);
        // 构造要更新的字段
        ChargeOrderItem chargeOrderItem = new ChargeOrderItem();
        chargeOrderItem.setPayStatus(PayStatusEnum.PAID.getValue());
        chargeOrderItem.setPayChannel(orderPayDTO.getPayChannel());
        chargeOrderItem.setChargeUserId(orderPayDTO.getChargeUserId());
        chargeOrderItem.setChargeBy(orderPayDTO.getChargeBy());
        chargeOrderItem.setChargeTime(now);
        chargeOrderItem.setUpdateUserId(orderPayDTO.getChargeUserId());
        chargeOrderItem.setUpdateBy(orderPayDTO.getChargeBy());
        chargeOrderItem.setUpdateTime(now);

        // 执行更新
        int updated = chargeOrderItemMapper.updateByExampleSelective(chargeOrderItem, example);
        if (updated == 0) {
            throw new BusinessFailException("支付失败，请稍后再试");
        }
    }


    /**
     * 查询指定订单的收费明细项
     * @param orderId 订单ID
     * @return 明细项列表
     */
    public List<ChargeOrderItem> getOrderItemList(Long orderId,List<String> itemTypeList) {
        ChargeOrderItemExample example = new ChargeOrderItemExample();
        ChargeOrderItemExample.Criteria criteria = example.createCriteria();
        criteria.andOrderIdEqualTo(orderId);
        if(!CollectionUtils.isEmpty(itemTypeList)){
            criteria.andItemTypeIn(itemTypeList);
        }
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        return chargeOrderItemMapper.selectByExample(example);
    }

    /**
     * 订单退款
     * @param chargeOrder
     */
    @Transactional(rollbackFor = Exception.class)
    public void refundOrder(ChargeOrder chargeOrder){
        ChargeOrder dbChargeOrder = getOrderById(chargeOrder.getOrderId());
        if(dbChargeOrder == null){
            throw new BusinessFailException("订单不存在");
        }
        dbChargeOrder.setPayStatus(PayStatusEnum.CANCELED.getValue());
        dbChargeOrder.setUpdateUserId(chargeOrder.getUpdateUserId());
        dbChargeOrder.setUpdateBy(chargeOrder.getUpdateBy());
        dbChargeOrder.setUpdateTime(new Date());
        chargeOrderMapper.updateByPrimaryKeySelective(dbChargeOrder);
    }

}
